package svm;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class matrixToFile
{
   private File fIn, fOut;
   private FileReader fr;
   private FileWriter fo;
   private final int[] firstLine = new int[] { 48, 32, 49, 58 };
   private final int[] firstLineTrain = new int[] { 32, 49, 58 };
   private static final int MAGIC = 48, START = 2, TRAIN_SIZE = 3,
         LINE_SIZE = 4;
   
   /**
    * This class takes a matrix as input and writes its contents into a text file
    * as something that is readable by the svm code. 
    * 
    * @param s String name of the file containing the matrix
    * @param train True if this is a training matrix
    */
   public matrixToFile(final String s, final boolean train, final int[] trainClass)
   {
      try {
         openFile(s);
      }
      catch (final FileNotFoundException e) {
         System.out.println(e.getMessage());
         System.exit(-1);
      }
      try {
         if (train) {
            writeFileTrain(trainClass);
         }
         else {
            writeFileSVM(trainClass);
         }
         
         fr.close();
         fo.close();
      }
      catch (final IOException e) {
         System.out.println(e.getMessage());
         System.exit(-1);
      }
   }
   
   /**
    * Opens a file and creates a fileReader to read it
    * 
    * @param s The name of the matrix File
    * @throws FileNotFoundException 
    */
   private void openFile(final String s) throws FileNotFoundException
   {
      fIn = new File(s);
      fr = new FileReader(fIn);
   }
   
   /**
    * Write to file if this is a training file
    * 
    * @param trainClass The classifications already known stored in an int[]
    * @throws IOException 
    */
   private void writeFileTrain(final int[] trainClass) throws IOException
   {
      fOut = new File("svmTrain");
      fo = new FileWriter(fOut);
      writeFile(true, trainClass);
   }
   
   /**
    * Write to file if this is not a training file
    * 
    * @throws IOException 
    */
   private void writeFileSVM(final int[] trainClass) throws IOException
   {
      fOut = new File("svmFile");
      fo = new FileWriter(fOut);
      writeFile(false, trainClass);
   }
   
   /**
    * Write to file
    * 
    * @param train True if this is a training file
    * @throws IOException 
    */
   private void writeFile(final boolean train, final int[] trainClass) throws IOException
   {
      int newChar = 0, count = START, pos = 0;
      
      /*
       * Adds the classification to the front if this is a training file
       * and if not then it writes a predetermined string that the svm 
       * platform can read. 
       */
      if (train)
      {
         fo.write(trainClass[pos++] + MAGIC);
         for (int i = 0; i < TRAIN_SIZE; i++)
         {
            fo.write(firstLineTrain[i]);
         }
      }
      else
      {
         for (int i = 0; i < LINE_SIZE; i++)
         {
            fo.write(firstLine[i]);
         }
         
      }
      
      newChar = fr.read();
      while (newChar != -1)
      {
         if (newChar != '\n')
         {
            /*
             * As long as a number is read in print it back otherwise add
             * a space and the position in the matrix. 
             */
            if (newChar >= '0' && newChar <= '9' ||
                  newChar == '.' || newChar == 'E' || newChar == '-')
            {
               fo.write(newChar);
            }
            else
            {
               fo.write(' ');
               fo.write(String.valueOf(count++));
               fo.write(':');
            }
         }
         else
         {
            newChar = fr.read();
            /*
             * If at the end of file then newChar will be -1
             */
            if (newChar != -1)
            {
               fo.write('\n');
               /*
                * Write predetermined beginings of the line so that the svm
                * platform can read the file.
                */
               if (train)
               {
                  fo.write(trainClass[pos++] + MAGIC);
                  for (int i = 0; i < TRAIN_SIZE; i++)
                  {
                     fo.write(firstLineTrain[i]);
                  }
                  fo.write(newChar);
               }
               else
               {
                  for (int i = 0; i < LINE_SIZE; i++)
                  {
                     fo.write(firstLine[i]);
                  }
                  fo.write(newChar);
               }
               count = START;
            }
         }
         
         newChar = fr.read();
      }
      
      int k = 5;
      k = k + 1;
      
   }
   
   /**
    * Deletes the files created by this class.
    * 
    * @throws IOException 
    */
   public void deleteFiles()
   {
      if (!fOut.delete()) {
         System.exit(-1);
      }
   }
}
